<script setup>
defineOptions({
  name: 'Threejs1'
})
import { onMounted } from 'vue'
import * as Cesium from 'cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'

onMounted(() => {
  console.log(Cesium, 'Cesium')

  // 设置 Cesium Ion 的 Access Token
  Cesium.Ion.defaultAccessToken =
    'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1YmYwYzdiNy1mOWQ5LTRiY2YtYWI1ZS0yMmMxMzNhYjUxYmQiLCJpZCI6MTkxNTc5LCJpYXQiOjE3MDYwNjY0Nzl9.hb31t0PlQP1ty-DYGNny7H2B8qFpqFprpJ6cRc2z_Hc'
  const arcGisTerrain = new Cesium.ArcGISTiledElevationTerrainProvider({
    url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer'
  })
  const viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: new Cesium.EllipsoidTerrainProvider(),
    scene3DOnly: true // 3D 模式下显示地形数据
    // globe: false // 不显示地球表面，只显示地形数据

    // terrainProvider: arcGisTerrain // 加载地形数据
  })
  // 移除默认的 Cesium 水印（可选）
  viewer.cesiumWidget.creditContainer.style.display = 'none'

  // 时间轴控件
  clockControl(viewer)

  // 加载 boat.glb 模型
  loadBoatModel(viewer)
})
// 加载 3D 模型
function loadBoatModel(viewer) {
  // 方法一 使用 SampledPositionProperty 移动模型位置
  // // 位置转换为笛卡尔坐标：模型位置（经度、纬度 、 高度）
  // // 初始位置
  // const startPosition = Cesium.Cartesian3.fromDegrees(121.801921, 31.32012, 0)
  // // 目标位置
  // const endPosition = Cesium.Cartesian3.fromDegrees(122.0, 31.32012, 0)

  // // 创建时间样本,移动的时间
  // const startTime = Cesium.JulianDate.fromDate(new Date())
  // const stopTime = Cesium.JulianDate.addSeconds(startTime, 10, new Cesium.JulianDate())

  // // 使用 SampledPositionProperty 创建位置属性
  // const positionProperty = new Cesium.SampledPositionProperty()
  // // 添加一个新样本。
  // positionProperty.addSample(startTime, startPosition)
  // positionProperty.addSample(stopTime, endPosition)

  // 方法二 使用 CallbackProperty 移动模型位置
  // 初始位置
  const currentPosition = Cesium.Cartesian3.fromDegrees(121.801921, 31.32012, 0)
  const targetPosition = Cesium.Cartesian3.fromDegrees(122.0, 31.32012, 0)
  const duration = 10 // 动画持续时间（秒）
  const startTime = Cesium.JulianDate.fromDate(new Date())

  // 使用 CallbackProperty 创建位置属性
  const positionProperty = new Cesium.CallbackProperty(
    function (time, result) {
      const deltaTime = Cesium.JulianDate.secondsDifference(time, startTime)
      const fraction = Cesium.Math.clamp(deltaTime / duration, 0.0, 1.0)

      // 插值计算当前位置
      Cesium.Cartesian3.lerp(currentPosition, targetPosition, fraction, result)
    },
    false // 表示不需要将结果克隆
  )
  console.log(positionProperty, 'positionProperty')

  // 添加模型
  const boatEntity = viewer.entities.add({
    name: 'Boat',
    position: currentPosition, // positionProperty
    model: {
      uri: '/public/models/boat.glb', // 模型路径
      minimumPixelSize: 128, // 最小渲染尺寸
      maximumScale: 100 // 最大缩放比例
    }
  })

  // 相机飞向模型
  viewer.flyTo(boatEntity)
}

// 时间轴控件设置
function clockControl(viewer) {
  viewer.clock.startTime = Cesium.JulianDate.fromIso8601('2025-01-01T00:00:00Z')
  viewer.clock.currentTime = Cesium.JulianDate.fromIso8601('2025-01-01T00:00:00Z')
  viewer.clock.stopTime = Cesium.JulianDate.fromIso8601('2025-12-31T23:59:59Z')
  viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // 循环播放
  viewer.clock.multiplier = 1000 // 时间流速
  viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime)
  formatterClock(viewer)
}
/** 时间轴格式化时间显示 */
function formatterClock(viewer, clock) {
  const formatTime = (date) => {
    const julianDT = Cesium.JulianDate.addHours(date, 8, new Cesium.JulianDate())
    const gregorianDate = Cesium.JulianDate.toGregorianDate(julianDT)
    const pad = (num) => num.toString().padStart(2, '0')

    return {
      year: gregorianDate.year,
      month: pad(gregorianDate.month),
      day: pad(gregorianDate.day),
      hour: pad(gregorianDate.hour),
      minute: pad(gregorianDate.minute),
      second: pad(gregorianDate.second)
    }
  }
  // 设置动画时间格式化器
  viewer.animation.viewModel.timeFormatter = (datetime) => {
    const time = formatTime(datetime)
    return `${time.hour}:${time.minute}:${time.second}`
  }

  // 设置时间轴标签格式化器
  viewer.timeline.makeLabel = (date) => {
    const time = formatTime(date)
    return `${time.year}年${time.month}月${time.day}日 ${time.hour}:${time.minute}:${time.second}`
  }
}
</script>

<template>
  <div id="cesiumContainer" style="width: 100vw; height: 800px"></div>
</template>

<style lang="less" scoped></style>
